﻿
#region 类描述


/*
 * 类    名：UEntity
 * 
 * 功能描述：实体数据处理工厂
 * 
 * 创 建 者：CHZ
 * 
 * 创建日期：2012.8.12
 * 
*/
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Reflection;
using System.ComponentModel;
using System.Data;
using System.Linq.Expressions;
using System.Collections.ObjectModel;


namespace PUBCOM
{

    public  class UEntity<T> : IUEntity<T> where T : class, new()
    {

        #region IUEntity<T> 成员
       
        /// <summary>
        /// 根据ID删除数据
        /// </summary>
        /// <param name="Id"></param>
        public int Delete(object Id)
        {
            SQLObject sql = CreateTxSQL.IC_Delete_SQL(new T(), Id);
            return DbHelperSQL.ExecuteSql(sql.TSQL, sql.Parms);
        }
        public int Delete(LambdaExpression lambda)
        {
            SQLObject sql = CreateTxSQL.IC_Delete_SQL(lambda);
            return DbHelperSQL.ExecuteSql(sql.TSQL);
        }
        /// <summary>
        /// 物理删除
        /// </summary>
        /// <param name="TableName">表名</param>
        /// <param name="keyField">字段名</param>
        /// <param name="val">值</param>
        /// <param name="notOrNonot">true =  false in</param>
        /// <returns></returns>
        public int Delete(string TableName, string keyField, object val, bool notOrNonot)
        {
            SQLObject sql = CreateTxSQL.IC_Delete_SQL(TableName, keyField, val, notOrNonot);
            return DbHelperSQL.ExecuteSql(sql.TSQL);
        }
        public int Delete(string TableName, string Where)
        {
            SQLObject sql = CreateTxSQL.IC_Delete_SQL(TableName, Where );
            return DbHelperSQL.ExecuteSql(sql.TSQL);
        }
        /// <summary>
        /// 未实现
        /// </summary>
        /// <param name="query">SQL语句</param>
        /// <param name="pars">参数</param>
        /// <returns></returns>
        public IList<T> ExecuteQuery(string query, params object[] pars)
        {
            throw new NotImplementedException();
        }

        #region 根据条件获得对象
        /// <summary>
        /// 根据主键值返回数据记录并填充对象
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public T GetById(object Id)
        {
            T t = new T();
            SQLObject eSql = CreateTxSQL.IC_Select_Single_SQL(t, Id);
            DataSet ds = DbHelperSQL.Query(eSql.TSQL, eSql.Parms);
            if (ds.Tables[0].Rows.Count > 0)
                FillObject(ds.Tables[0].Rows[0], t);

            return t;
        }

        /// <summary>
        /// 指定字段名查询
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="KeyFiled"></param>
        /// <returns></returns>
        public T GetById(object Id, string KeyFiled)
        {
             T t = new T();
             SQLObject eSql = CreateTxSQL.IC_Select_Single_SQL(t,KeyFiled, Id);
            DataSet ds = DbHelperSQL.Query(eSql.TSQL, eSql.Parms);
            if (ds.Tables[0].Rows.Count > 0)
                 FillObject(ds.Tables[0].Rows[0], t);
            return t;
        }

        public T GetByWhere(LambdaExpression lambda)
        {
            List<T> listT=ToList<T>(ReFirstTable(CreateTxSQL.IC_Select_SQL(1, lambda)));
            if (listT.Count > 0)
                return listT[0];
            else return null;
        }
        #endregion

        #region 新增
        /// <summary>
        /// 单新增
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int Insert(T entity)
        {
            SQLObject sql = CreateTxSQL.IC_Insert_SQL(entity);
            return DbHelperSQL.ExecuteSql(sql.TSQL,sql.Parms);
        }

        /// <summary>
        /// 多对象新增
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public int Insert(IEnumerable<T> list)
        {
            return 0;
        }

        #endregion

        #region 更新

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public int Update(T target)
        {
            SQLObject sql = CreateTxSQL.IC_Update_SQL(target);
            return DbHelperSQL.ExecuteSql(sql.TSQL, sql.Parms);
        }

        #endregion

        #region 单对象指定返回记录数

        /// <summary>
        /// 查询记录
        /// </summary>
        /// <param name="top">指定返回数：0为全部，其他为指定数</param>
        /// <param name="target">条件对象</param>
        /// <returns></returns>
        public IList<T> GetTopList(int top, T target)
        {
            SQLObject sql = CreateTxSQL.IC_Select_SQL(target, top);
            DataSet ds = DbHelperSQL.Query(sql.TSQL, sql.Parms);
            return ToList<T>(ds.Tables[0]);
        }

        /// <summary>
        /// 查询记录
        /// </summary>
        /// <param name="top">指定返回数：0为全部，其他为指定数</param>
        /// <returns></returns>
        public IList<T> GetTopList(int top)
        {
            return GetTopList(top, new T());
        }

        #endregion

        #region 分页查询

        /// <summary>
        /// 分页查询数据
        /// </summary>
        /// <param name="query">分页参数</param>
        /// <param name="RecordCount">返回记录数</param>
        /// <returns></returns>
        public IList<T> GetList(QueryParam query, out int RecordCount)
        {
            return ToList<T>(SearchList(query, new T(), false, out RecordCount));
        }

        /// <summary>
        /// 返回带分页实体列表
        /// </summary>
        /// <param name="query">分页实体</param>
        /// <param name="target">查询条件实体</param>
        /// <param name="RecordCount">返回记录数</param>
        /// <returns></returns>
        public IList<T> GetList(QueryParam query,T target,out int RecordCount)
        {
            return ToList<T>(SearchList(query, target, true, out RecordCount));
        }

        /// <summary>
        /// 返回带分页数据表
        /// </summary>
        /// <param name="query">分页实体</param>
        /// <param name="target">查询条件实体</param>
        /// <param name="RecordCount">返回记录数</param>
        /// <returns></returns>
        DataTable IUEntity<T>.GetListTable(QueryParam query, T target, out int RecordCount)
        {
            return SearchList(query, target, true, out RecordCount);
        }

        /// <summary>
        /// 实现分页数据返回
        /// </summary>
        /// <param name="query">分页实体</param>
        /// <param name="entity"></param>
        /// <param name="checkModel">查询条件实体</param>
        /// <param name="RecordCount">返回记录数</param>
        /// <returns></returns>
        protected DataTable SearchList(QueryParam query, T entity, bool checkModel, out int RecordCount)
        {
            SQLObject sql = CreateTxSQL.IC_Select_SQL(entity, query, checkModel);
            DataSet ds = DbHelperSQL.RunProcedure(sql.TSQL, sql.Parms, "GetListPage");
            RecordCount = DataConverter.CLng(ds.Tables["GetListPage1"].Rows[0]["RecordCount"].ToString());
            return ds.Tables["GetListPage"];
        }

        /// <summary>
        /// 返回带分页实体列表
        /// </summary>
        /// <param name="query">分页实体</param>
        /// <param name="lambda">Lambda 表达式</param>
        /// <param name="RecordCount">返回记录数</param>
        /// <returns></returns>
        public DataTable  GetList(QueryParam query, LambdaExpression lambda,  out int RecordCount)
        {
            query.Where = CreateTxSQL.Combination(null,ExpressionProvider.ToSql(lambda.Body));
            StringBuilder tables = new StringBuilder();
            if (lambda.Parameters != null)
            {
                foreach (ParameterExpression pr in lambda.Parameters)
                {
                    tables.Append(CreateTxSQL.GetObjectBinderTableName(pr.Type) + " " + pr.Name + ",");
                    query.Where = query.Where.Replace(pr.Name+".","");
                }
            }
            query.TableName =lambda.Parameters.Count>1? tables.ToString().Trim(','):CreateTxSQL.GetObjectBinderTableName(typeof(T));
            SQLObject sql = CreateTxSQL.IC_Select_SQL(query);
            DataSet ds = DbHelperSQL.RunProcedure(sql.TSQL, sql.Parms, "GetListPage");
            RecordCount = DataConverter.CLng(ds.Tables["GetListPage1"].Rows[0]["RecordCount"].ToString());
            return ds.Tables["GetListPage"];
        }


        #endregion

        #region 自定义查询

        /// <summary>
        /// 返回所有数据
        /// </summary>
        /// <returns></returns>
        public DataTable GetList()
        {
            return GetList(0, new T());
        }

        /// <summary>
        /// 返回所有数据
        /// </summary>
        /// <param name="top">查询记录数</param>
        /// <param name="lambda">Lambda条件表达式</param>
        /// <returns>数据类型DataTable</returns>
        public DataTable D_GetList(int top,LambdaExpression lambda)
        {
            return ReFirstTable(CreateTxSQL.IC_Select_SQL(top,lambda));
        }


        /// <summary>
        /// 根据Lambda条件表达式返回数据列表
        /// </summary>
        /// <param name="lambda">Lambda条件表达式</param>
        /// <returns></returns>
        public List<T> GetList(LambdaExpression lambda)
        {
            return GetList(0, lambda);
        }

        /// <summary>
        /// 查询记录
        /// </summary>
        /// <param name="top">指定返回数：0为全部，其他为指定数</param>
        /// <param name="target">条件对象</param>
        /// <returns></returns>
        public DataTable GetList(int top, T target)
        {
            return ReFirstTable(CreateTxSQL.IC_Select_SQL(target, top));
        }

        /// <summary>
        /// 根据Lambda条件表达式返回数据列表
        /// </summary>
        /// <param name="lambda">Lambda条件表达式</param>
        /// <returns></returns>
        public List<T> GetList(int top,LambdaExpression lambda)
        {
            return ToList<T>(ReFirstTable(CreateTxSQL.IC_Select_SQL(top,lambda)));
        }

        /// <summary>
        /// 多条件多表关联查询数据
        /// </summary>
        /// <param name="fileds">返回字段</param>
        /// <param name="lambda">Lambda条件表达式</param>
        /// <returns></returns>
        public DataTable GetList(string[] fileds, LambdaExpression lambda)
        {
            SQLObject sql = new SQLObject();
            sql.TSQL = CreateTxSQL.IC_Select_SQL(fileds, lambda);
            sql.Parms = null;
            return ReFirstTable(sql);
        }

        /// <summary>
        /// 多条件多表关联查询数据
        /// </summary>
        /// <param name="fileds">返回字段</param>
        /// <param name="lambda">Lambda条件表达式</param>
        /// <returns></returns>
        public DataTable GetList(string returnField, LambdaExpression lambda, string orderField)
        {
            SQLObject sql = new SQLObject();
            sql.TSQL = CreateTxSQL.IC_Select_SQL(returnField, lambda, orderField);
            sql.Parms = null;
            return ReFirstTable(sql);
        }

        

        #endregion

        #endregion

        #region 数据处理厂
        /// <summary>
        /// 返回数据表
        /// </summary>
        /// <param name="sql">SQLObject实体对象</param>
        /// <returns></returns>
        public DataTable ReFirstTable(SQLObject sql)
        {
            return DbHelperSQL.Query(sql.TSQL, sql.Parms).Tables[0];
        }

        /// <summary>
        /// 返回数据集合（DataSet）
        /// </summary>
        /// <param name="sql">SQLObject实体对象</param>
        /// <returns></returns>
        public DataSet ReDataSet(SQLObject sql)
        {
            return DbHelperSQL.Query(sql.TSQL, sql.Parms);
        }
        #endregion

        #region 辅助方法

        #region 填充当前对象
        /// <summary>
        /// 填充当前对象
        /// </summary>
        /// <param name="dr"></param>
        public virtual void SetObject(DataRow dr,object obj)
        {
            var properties = TypeDescriptor.GetProperties(obj.GetType());
            var fields = Enumerable.Range(0, dr.Table.Columns.Count);
            fields.ToList().ForEach(field => { properties[field].SetValue(obj, dr[field] == DBNull.Value ? null : dr[field]); });
        }

        /// <summary>
        /// 填充当前对象
        /// </summary>
        /// <param name="dr"></param>
        public virtual void FillObject(DataRow dr,object obj)
        {
            Type _Obj = obj.GetType();
            PropertyInfo[] propertys = _Obj.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            object D0bj = null;
            foreach (PropertyInfo property in propertys)
            {
                #region

                Type columnType = property.PropertyType;
                if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    columnType = property.PropertyType.GetGenericArguments()[0];
                }

                D0bj = dr[property.Name];
                switch (columnType.Name.ToString())
                {
                    case "Boolean":
                        property.SetValue(obj, DataConverter.CBoolean(D0bj.ToString()), null);
                        break;
                    case "Byte":
                        property.SetValue(obj, Convert.ToByte(D0bj), null);
                        break;
                    case "Char":
                        property.SetValue(obj, Convert.ToChar(D0bj), null);
                        break;
                    case "SByte":
                        property.SetValue(obj, Convert.ToSByte(D0bj), null);
                        break;
                    case "Int16":
                        property.SetValue(obj, Convert.ToInt16(D0bj), null);
                        break;
                    case "Int32":
                        property.SetValue(obj, DataConverter.CLng(D0bj), null);
                        break;
                    case "UInt32":
                        property.SetValue(obj, Convert.ToUInt32(D0bj), null);
                        break;
                    case "Int64":
                        property.SetValue(obj, Convert.ToInt64(D0bj), null);
                        break;
                    case "String":
                        property.SetValue(obj, D0bj.ToString(), null);
                        break;
                    case "DateTime":
                        property.SetValue(obj, Check.ToDateTime(D0bj.ToString()), null);
                        break;
                    case "Double":
                        property.SetValue(obj, DataConverter.CDouble(D0bj.ToString()), null);
                        break;
                    case "Float":
                        property.SetValue(obj, DataConverter.CSingle(D0bj.ToString()), null);
                        break;
                    case "Decimal":
                        property.SetValue(obj, DataConverter.CDecimal(D0bj.ToString()), null);
                        break;
                }
                #endregion
            }
        }

        #endregion

        #region DataTalbe转化成对象列表
        /// <summary>
        /// 返回列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public List<T> ToList<T>(DataTable dt) where T : class, new()
        {
            List<T> list = new List<T>();
            T o = new T();
            foreach (DataRow dr in dt.Rows)
            {
                o = new T();
               FillObject(dr, o);
               //  SetObject(dr, o);
                list.Add(o);
            }
            return list;
        }
        #endregion

        #endregion

        #region 扩展成员

        /// <summary>
        /// 检查数据
        /// </summary>
        /// <param name="fileds"></param>
        /// <returns></returns>
        public bool Exists(Dictionary<string, object> fileds)
        {
            SQLObject eSql = CreateTxSQL.IC_Exists_SQL(new T(), fileds);
            return DbHelperSQL.Exists(eSql.TSQL, eSql.Parms);
        }

        /// <summary>
        /// 唯一性
        /// </summary>
        /// <param name="lambda">条件表达式</param>
        /// <returns></returns>
        public bool Exists(LambdaExpression lambda)
        {
            return DbHelperSQL.Exists(CreateTxSQL.IC_Existes_SQL(lambda));
        }

        /// <summary>
        /// 返回最大值
        /// </summary>
        /// <param name="filed"></param>
        /// <param name="lambda"></param>
        /// <returns></returns>
        public string Max(string filed, LambdaExpression lambda)
        {
            object v_max=DbHelperSQL.GetSingle(CreateTxSQL.IC_Max_SQL(filed,lambda));
            return v_max == null ? "" : v_max.ToString();
        }
        #endregion

    }
    
}